from collections.abc import Sequence
from typing import Any, Dict
from enum import Enum
import operator
from core.enums import BuildTreeType
from utils.serializers import select_list_serialize,RowData

def get_tree_nodes(row: Sequence[RowData], *, is_sort: bool, sort_key: str) -> list[dict[str, Any]]:
    """
    获取所有树形结构节点

    :param row: 原始数据行序列
    :param is_sort: 是否启用结果排序
    :param sort_key: 基于此键对结果进行进行排序
    :return:
    """
    tree_nodes = select_list_serialize(row)
    if is_sort:
        tree_nodes.sort(key=operator.itemgetter(sort_key))
    return tree_nodes


def traversal_to_tree(nodes: list[dict[str,Any]]) -> list[dict[str,Any]]:
    """
    将遍历算法生成的节点列表转换为树形结构

    :param nodes: 遍历算法生成的节点列表
    :return: 树形结构数据
    """
    tree: list[dict[str, Any]] = []
    node_dict = {node['id']: node for node in nodes}
    for node in nodes:
        parent_id = node['parent_id']
        if parent_id is None:
            tree.append(node)
        else:
            parent_node = node_dict.get(parent_id)
            if parent_node is not None:
                if 'children' not in parent_node:
                    parent_node['children'] = []
                if node not in parent_node['children']:
                    parent_node['children'].append(node)
            else:
                if node not in tree:
                    tree.append(node)

    return tree

def recursive_to_tree(nodes: list[dict[str, Any]], *, parent_id: int | None = None) -> list[dict[str, Any]]:
    """
    通过递归算法构造树形结构（性能影响较大）

    :param nodes: 树节点列表
    :param parent_id: 父节点 ID，默认为 None 表示根节点
    :return:
    """
    tree: list[dict[str, Any]] = []
    for node in nodes:
        if node['parent_id'] == parent_id:
            child_nodes = recursive_to_tree(nodes, parent_id=node['id'])
            if child_nodes:
                node['children'] = child_nodes
            tree.append(node)
    return tree


def get_tree_data(
    row: Sequence[RowData],
    build_type: BuildTreeType = BuildTreeType.traversal,
    *,
    parent_id: int | None = None,
    is_sort: bool = True,
    sort_key: str = 'sort',
) -> list[dict[str, Any]]:
    """
    获取树形结构数据

    :param row: 原始数据行序列
    :param build_type: 构建树形结构的算法类型，默认为遍历算法
    :param parent_id: 父节点 ID，仅在递归算法中使用
    :param is_sort: 是否启用结果排序
    :param sort_key: 基于此键对结果进行进行排序
    :return:
    """

    nodes = get_tree_nodes(row, is_sort=is_sort,sort_key=sort_key,)
    match build_type:
        case BuildTreeType.traversal:
            tree = traversal_to_tree(nodes)
        case BuildTreeType.recursion:
            tree = recursive_to_tree(nodes, parent_id=parent_id)
        case _:
            raise ValueError(f"未知的构建树形结构算法类型: {build_type}") 
    return tree


def get_art_tree_data(
    row: Sequence[RowData],
    *,
    is_sort: bool = True,
    sort_key: str = 'sort',
) -> list[dict[str, Any]]:
    """
    获取菜单树形结构数据（按当前业务结构生成，内含按钮聚合与排序）

    :param row: 原始数据行序列
    :param is_sort: 是否启用结果排序
    :param sort_key: 基于此键对结果进行进行排序
    :return: 业务结构的菜单树（包含 meta 与 children，并将按钮聚合到父菜单的 meta.authList）
    """
    # 先将原始数据序列化并排序
    raw_nodes = get_tree_nodes(row, is_sort=is_sort, sort_key=sort_key)

    # 分离菜单与按钮（type == 2 为按钮）
    menu_nodes: list[dict[str, Any]] = []
    button_nodes: list[dict[str, Any]] = []
    for node in raw_nodes:
        if node.get('type') == 2:
            button_nodes.append(node)
            continue
        meta = {
            'title': node.get('name') or node.get('title') or '',
            'icon': node.get('icon'),
            'showBadge': None,
            'showTextBadge': None,
            'isHide': node.get('is_hidden'),
            'isHideTab': None,
            'link': node.get('link'),
            'isIframe': node.get('is_iframe'),
            'keepAlive': node.get('keep_alive') if 'keep_alive' in node else node.get('cache'),
            'authList': node.get('meta', {}).get('authList', []),
            'isFirstLevel': None,
            'roles': None,
            'fixedTab': None,
            'activePath': None,
            'isFullPage': None,
            'isAuthButton': None,
            'authMark': None,
            'parentPath': None,
        }

        new_node = dict(node)
        new_node['meta'] = meta
        menu_nodes.append(new_node)

    # 构建树
    tree = traversal_to_tree(menu_nodes)

    # 建立 id->node 索引
    index: Dict[int, Dict[str, Any]] = {}
    def _walk(n: Dict[str, Any]):
        nid = n.get('id')
        if nid is not None:
            index[nid] = n
        for c in n.get('children', []) or []:
            _walk(c)
    for r in tree:
        _walk(r)

    # 将按钮聚合到父菜单的 meta.authList；无父级则追加为根节点
    for btn in button_nodes:
        parent_id = btn.get('parent_id')
        payload = {
            'id': btn.get('id'),
            'title': btn.get('name'),
            'authMark': btn.get('code'),
        }
        if parent_id and parent_id in index:
            meta = index[parent_id].setdefault('meta', {})
            auth_list = meta.setdefault('authList', [])
            auth_list.append(payload)
        else:
            tree.append({
                'id': btn.get('id'),
                'name': btn.get('name'),
                'code': btn.get('code'),
                'type': btn.get('type'),
                'path': btn.get('path'),
                'component': btn.get('component'),
                'sort': btn.get('sort'),
                'meta': {
                    'title': btn.get('name'),
                    'icon': btn.get('icon'),
                    'isHide': btn.get('is_hidden'),
                    'keepAlive': btn.get('keep_alive') if 'keep_alive' in btn else btn.get('cache'),
                    'isIframe': btn.get('is_iframe'),
                    'link': btn.get('link'),
                    'authList': [payload],
                    'showBadge': None,
                    'showTextBadge': None,
                    'isHideTab': None,
                    'isFirstLevel': None,
                    'roles': None,
                    'fixedTab': None,
                    'activePath': None,
                    'isFullPage': None,
                    'isAuthButton': None,
                    'authMark': None,
                    'parentPath': None,
                },
                'children': [],
            })

    # 统一按 sort,id 排序每层
    def _sort_children(nodes: list[dict[str, Any]]):
        nodes.sort(key=lambda x: (x.get('sort', 0), x.get('id', 0)))
        for n in nodes:
            _sort_children(n.get('children', []) or [])

    _sort_children(tree)
    return tree
